package com.agentai.framework.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

/**
 * @Author yangfei
 * @Description
 * @Date 2024/5/21 10:32
 */
@Component
@Slf4j
public class NettyServer {


    private EventLoopGroup bossGroup;
    private EventLoopGroup workGroup;
    private ChannelFuture future;

    @Autowired
    ProjectInitializer nettyInitializer;

    @Autowired
    WebSocketConfig webSocketConfig;

    @PostConstruct
    public void start() throws InterruptedException {
        new Thread(() -> {
            bossGroup = new NioEventLoopGroup(webSocketConfig.getBoss());
            workGroup = new NioEventLoopGroup(webSocketConfig.getWork());
            ServerBootstrap bootstrap = new ServerBootstrap();
            // bossGroup辅助客户端的tcp连接请求, workGroup负责与客户端之前的读写操作
            bootstrap.group(bossGroup, workGroup);
            // 设置NIO类型的channel
            bootstrap.channel(NioServerSocketChannel.class);
            // 设置监听端口
            bootstrap.localAddress(new InetSocketAddress(webSocketConfig.getPort()));
            // 设置管道
            bootstrap.childHandler(nettyInitializer);

            // 配置完成，开始绑定server，通过调用sync同步方法阻塞直到绑定成功
            try {
                future = bootstrap.bind().sync();
                log.info("Server started and listen on:{}", future.channel().localAddress());
                // 对关闭通道进行监听
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 释放资源
     */
    @PreDestroy
    public void destroy() throws InterruptedException {
        log.info("Netty WebSocket server closing...");
        try {
            if (future != null)
                future = future.channel().closeFuture();
            if (bossGroup != null)
                bossGroup.shutdownGracefully().sync();
            if (workGroup != null)
                workGroup.shutdownGracefully().sync();
            if (future != null)
                future.sync();
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
        log.info("Netty WebSocket server closed.");
    }
}
